//游戏控制逻辑
export class GameCon{
  //游戏格子
  gameArr: number[][]=[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
  isGameOver:boolean = false
  //初始化游戏分数
  score: number = 0;
  scareValue: number = 1;
  scoreAddition: number = 0;
  merged: boolean = false

  //init 方法用于初始化游戏状态。
  init(gameArr:number[]){
    this.score = 0
    for(let i=0;i<4;i++){
      for(let j=0;j<4;j++){
        this.gameArr[i][j]=gameArr[i*4+j]
      }
    }
    this.isGameOver=false
    //填充两个随机的非零数字到空白的格子中
    this.fillOneEmptyGame()
    this.fillOneEmptyGame()
  }
  //找到可以用于生成新数字的单元格，并生成新的数字进行填充
  fillOneEmptyGame() {
    let gameIndex= this.findOneEmptyGame()
    if(gameIndex!=-1){
      //转换为行号和列号
      let row = Math.floor(gameIndex/4)
      let col = gameIndex%4
      this.gameArr[row][col]=this.getRandomValue()
    }
  }
  //用于查找游戏数组中的空格子，并返回一个包含空格子索引的数组。
  findOneEmptyGame(){
    let games = []
    for (let i = 0; i < 4; i++) {
      for (let j = 0; j < 4; j++) {
        if (!this.gameArr[i][j]) {
          games.push(i * 4 + j)
        }
      }
  }
    if (games.length) {
      return games[this.randomVal(games.length)]
    } else {
      return -1
    }
  }
  //生成新的数字，并且设置生成概率
  getRandomValue(){
    return Math.random() < 0.9 ? 2 : 4;
  }
  //生成指定范围内的随机整数
  randomVal(max: number) {
    return Math.floor(Math.random() * max)
  }
  /*
       判断是否还可以移动。
       1、当前单元格是否为0；
       2、当前单元格和右侧单元格是否相等；
       3、当前单元格和下方单元格是否相等。
       */
  canMove(){
    //遍历二维数组
    for(let i=0; i<4;i++){
      for(let j=0;j<4;j++){
        let game= this.gameArr[i][j]
        if(game){
          //和右边比较，是否相等
          if (j<3 &&this.gameArr[i][j] == this.gameArr[i][j+1]) {
            return true
          }
          //和下方比较
          if (i<3&&this.gameArr[i][j] == this.gameArr[i+1][j]) {
            return true
          }
        }else {
          return true
        }
      }
    }
    return false
  }

//将二维数组转为一维数组
  getFlatGameArr(){
    var flatCellArr =[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    for (let i = 0; i < 4; i++) {
      for (let j = 0; j < 4; j++) {
        flatCellArr[i * 4+j] = this.gameArr[i][j]
      }
    }
    return flatCellArr
  }
  //将单元格数向左或向右移动，移除0并对相邻相同数进行叠加,toLeft表示是否向左
    MoveCells(toLeft:boolean){
      for(let i=0;i<4;i++){
        let newArr= Array(4).fill(0)
        let mergedValues = [];
        for(let j =0 ; j<4;j++){
          newArr[j]=this.gameArr[i][j]
        }
        let { newArr: resultArr, merged } = this.removeAndAdd(newArr, toLeft);
        this.merged = this.merged || merged;
        for(let j=0;j<4;j++){
          if (merged && this.gameArr[i][j] !== resultArr[j]) {
            mergedValues.push(resultArr[j]);
          }
          this.gameArr[i][j] = resultArr[j]
        }
      }
    }
// 将单元格数向下或向上移动，移除0并对相邻相同数进行叠加,toup表示是否向上
  varMoveCells(toUP:boolean){
    for(let i=0;i<4;i++){
      let newArr =Array(4).fill(8)
      let mergedValues = [];
       for(let j =0 ; j<4;j++){
         newArr[j]=this.gameArr[j][i]
       }
      let { newArr: resultArr, merged } =this.removeAndAdd(newArr,toUP)
      this.merged = this.merged || merged;
      for(let j=0;j<4;j++){
        if (merged && this.gameArr[i][j] !== resultArr[j]) {
          mergedValues.push(resultArr[j]);
        }
        this.gameArr[j][i]=resultArr[j]
      }
    }
  }

  /**
   * 1、去掉数组中的0，向头或向尾压缩数组。
   * 0,4,0,4向左压缩变成：4,4,0,0. 向右压缩变成：0,0,4,4
   * 2、相邻的数如果相同，则进行相加运算。
   * 4,4,0,0向左叠加变成：8,0,0,0. 向右叠加变成：0,0,0,8
   * toHead表示是否是头压缩
   */
  removeAndAdd(arr: number[], toHead: boolean): { newArr: number[], merged: boolean } {
    let newArr = Array(4).fill(0);
    let arrWithoutZero = arr.filter(x => x !== 0);
    let tempArr = [];
    let merged = false; // 用于标记是否发生了合并

    if (toHead) {
      for (let i = 0; i < arrWithoutZero.length; i++) {
        if (arrWithoutZero[i] === arrWithoutZero[i + 1]) {
          let mergedValue = arrWithoutZero[i] * 2;
          tempArr.push(mergedValue);
          this.UpdateScore(mergedValue)
          i++;
          merged = true;
        } else {
          tempArr.push(arrWithoutZero[i]);
        }
      }
    } else {
      for (let i = arrWithoutZero.length - 1; i >= 0; i--) {
        if (arrWithoutZero[i] === arrWithoutZero[i - 1]) {
          let mergedValue = arrWithoutZero[i] * 2;
          tempArr.unshift(mergedValue);
          this.UpdateScore(mergedValue)
          i--;
          merged = true;
        } else {
          tempArr.unshift(arrWithoutZero[i]);
        }
      }
    }
    // 根据是否向头部移动，填充新数组，以保持数组长度为4
    for (let i = 0; i < tempArr.length; i++) {
      newArr[toHead ? i : newArr.length - tempArr.length + i] = tempArr[i];
    }
    return { newArr, merged };
  }
  //检查游戏是否结束或者是否可以继续进行下一步操作
  checkGameOverOrContinue(){
    // 首先检查游戏是否可以继续进行，即是否还有空的单元格或者相邻单元格有相同数字可以合并
    if(this.canMove()){
      // 如果可以继续进行，则在空的单元格中填充一个新的数字
      this.fillOneEmptyGame();
    }else {
      //游戏结束
      this.isGameOver=true;
    }

  }
  moveUp(){
    this.merged = false; // 重置 merged 状态
    this.scoreAddition = 0; // 重置加分累计
    this.varMoveCells(true);
    this.checkGameOverOrContinue();
  }
  moveDown(){
    this.merged = false; // 重置 merged 状态
    this.scoreAddition = 0; // 重置加分累计
    this.varMoveCells(false);
    this.checkGameOverOrContinue();
  }
  moveLeft(){
    this.merged = false; // 重置 merged 状态
    this.scoreAddition = 0; // 重置加分累计
    this.MoveCells(true);
    this.checkGameOverOrContinue();
  }
  moveRight(){
    this.merged = false; // 重置 merged 状态
    this.scoreAddition = 0; // 重置加分累计
    this.MoveCells(false);
    this.checkGameOverOrContinue();
  }

  //更新游戏分数
  UpdateScore(mergedValue: number) {
    this.score += mergedValue; // 根据合并的值动态增加分数
    this.scoreAddition += mergedValue; // 累加本次移动操作的加分
  }
}